package util;

import Server.Sensor;
import ServidorCoordenadas.Cell;
import gui.Usuario;
import gui.frameAdmin;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;

import org.apache.commons.codec.binary.Base64;

import util.DBconnection;
import util.SocketManager;

public class Monitor2 implements Runnable {

	private SocketManager socket;
	private static int numCLiente;
	private static HashMap<String, Usuario> MapClientesConectados;
	private static int clientesMaximos = 2;
	private static DBconnection ConexionDB;
	private static ArrayList<Sensor> listaSensores;
	private static String CellID = "3053";
	private boolean salir;
	private static frameAdmin AdminWindow;

	static TimerTask timerTask = new TimerTask() {
		public void run() {
			System.out.println("Guardando DB");
			ConexionDB.guardadoAutomatico(listaSensores);
		}
	};
	static TimerTask sensorTask = new TimerTask() {
		public void run() {
			for (int i = 0; i < listaSensores.size(); i++) {
				listaSensores.get(i).crearMedida();
			}
			System.out.println("Tomando medidas del paciente");

		}
	};

	public Monitor2() throws SQLException {
		ConexionDB = new DBconnection();
		listaSensores = ConexionDB.obtenerLIstaSensores();
		MapClientesConectados = new HashMap<String, Usuario>();
		salir = false;
		AdminWindow = new frameAdmin();
		 AdminWindow.setVisible(true);
		 

	}

	public static void main(String argv[]) throws Exception // falta por
	{

		int puerto = 3000;
		ServerSocket monitorSocket = new ServerSocket(puerto);
		int cliente = 0;

		Monitor2 m1 = new Monitor2();

		

		Timer timer = new Timer();

		// timer.scheduleAtFixedRate(sensorTask, 20000, 60000);
		// timer.scheduleAtFixedRate(timerTask, 30000, 30000);

		while (true) {

			SocketManager monitorSocketManager = new SocketManager(
					monitorSocket.accept());
			m1.socket = monitorSocketManager;

			Thread thre = new Thread(m1);
			thre.start();
		}

	}

	@Override
	public void run() {

		SocketManager socketTemp = socket;

		String clientSentence = new String();
		String serverSentence = new String();
		String nombreUsuario = new String();
		String claveUsuario = new String();
		Boolean escuchando = true;
		int estado = 0;
		

		if (numCLiente <= clientesMaximos) {

			while (escuchando == true) {
				try {

					clientSentence = socketTemp.Leer();
					serverSentence = "";

				} catch (IOException e1) {

					e1.printStackTrace();

				}

				switch (estado) {
				case 0: {

					try {

						if (clientSentence.contains("USUARIO")) {

							if (clientSentence.equals("USUARIO")) {
								serverSentence = "501 ERR Falta el nombre de usuario.";

							} else {
								if (ConexionDB.comprobarCliente(clientSentence
										.substring(8)) == false) {

									serverSentence = "501 ERR usuario incorrecto.";
								} else {
									estado = 1;
									serverSentence = "OK Bienvenido"
											+ clientSentence
													.substring("USUARIO"
															.length() + 1);
									nombreUsuario = clientSentence.substring(8);
								}

							}

						} else {
							serverSentence = "Comando No reconocido.";
						}

						socketTemp.Escribir(serverSentence + "CLRF" + '\n'); // ENVIAR
																				// AL
																				// CLIENTE
																				// ESTADO
																				// 0

					} catch (IOException | SQLException e1) {
						try {
							socketTemp.CerrarSocket();
							socket.CerrarSocket();
						} catch (IOException e) {

							e.printStackTrace();
						}
						e1.printStackTrace();
					}

					break;
				}
				case 1: {
					try {
						if (clientSentence.contains("CLAVE")) {
							if (clientSentence.equals("CLAVE")) {
								serverSentence = "503 ERR Falta la clave.";

							} else {
								System.out.println();
								if (ConexionDB.comprobarContrasena(
										clientSentence.substring(6),
										nombreUsuario) == false) {
									serverSentence = "502 ERR clave incorrecta.";
								} else {
									claveUsuario = clientSentence.substring(6);
									estado = 2;
									Usuario u = new Usuario(nombreUsuario,
											clientSentence.substring(6), socket);
									this.MapClientesConectados.put(
											nombreUsuario, u);
									numCLiente++;
									serverSentence = "302 OK Bienvenido al sistema";
									// frameAdmin.insertarUsuario(nombreUsuario,
									// clientSentence.substring(6),
									// numCLiente);
								}

							}

						} else {
							serverSentence = "503 ERR Falta la clave.";
						}
						socketTemp.Escribir(serverSentence + "CLRF" + '\n'); // ENVIAR
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}

					break;
				}
				case 2: {
					try {
						if (clientSentence.equals("LISTSENSOR")) {
							String listsensor = new String();

							for (int i = 0; i < listaSensores.size(); i++) {
								listsensor = listaSensores.get(i)
										.getID_Sensor()
										+ ";"
										+ listaSensores.get(i).getTiposensor()
												.toString()
										+ ";"
										+ listaSensores.get(i).getEstado()
										+ "CRLF";
								socketTemp.Escribir(listsensor + '\n');
							}
							serverSentence = "322 OK Lista finalizada";

						} else if (clientSentence.contains("HISTORICO")) {

							if (clientSentence.equals("HISTORICO")) {
								serverSentence = "525 ERR Falta par�metro id_sensor.";
							} else {
								String string1 = clientSentence.substring(10);
								Sensor s1 = this.buscarSensor(Integer
										.parseInt(string1));
								if (s1 != null) {
									ArrayList<String> ar = ConexionDB
											.obtenerMedidasSensor(s1);
									String historico = new String();
									for (int i = 0; i < ar.size(); i++) {
										historico = ar.get(i);
										System.out.println(historico + " " + i);
										socketTemp.Escribir(historico + '\n');

									}

								}
								serverSentence = "322 OK Lista finalizada";

							}

						} else if (clientSentence.contains("ON")) {
							if (clientSentence.equals("ON ")) {
								serverSentence = "525 ERR Falta par�metro id_sensor.";
							} else if (buscarSensor(Integer
									.parseInt(clientSentence.substring(3))) != null) {
								Sensor s1 = buscarSensor(Integer
										.parseInt(clientSentence.substring(3)));
								s1.encender();
							}

						} else if (clientSentence.contains("OFF")) {
							if (clientSentence.length() == "OFF".length()) {
								serverSentence = "525 ERR Falta par�metro id_sensor.";

							} else if (buscarSensor(Integer
									.parseInt(clientSentence.substring(3))) != null) {
								Sensor s1 = buscarSensor(Integer
										.parseInt(clientSentence.substring(3)));
								s1.apagar();
							}

						} else if (clientSentence.equals("ONGPS")) {
							if (listaSensores.get(1).getEstado() == "ON") {

							} else {
								listaSensores.get(1).encender();
							}

						} else if (clientSentence.equals("OFFGPS")) {
							if (listaSensores.get(1).getEstado() == "OFF") {

							} else {
								listaSensores.get(1).apagar();
							}

						} else if (clientSentence.contains("GET_VALACT")) {
							if (clientSentence.length() == "GET_VALACT"
									.length()) {
								serverSentence = "525 ERR Falta parametro id_sensor";

							} else if (buscarSensor(Integer
									.parseInt(clientSentence.substring(11))) != null) {
								Sensor s1 = buscarSensor(Integer
										.parseInt(clientSentence.substring(11)));

								if (s1 != null) {
									if (s1.getEstado() == "OFF") {
										serverSentence = "526 ERR Sensor en OFF";
									} else {
										serverSentence = s1.getValorActual();
									}

								} else {
									serverSentence = "524 ERR Sensor Desconocido";
								}

							}
						} else if (clientSentence.equals("GET_FOTO")) {
							estado = 3;
							try {
								serverSentence = this.enviarImagen();
								socketTemp.Escribir(serverSentence + '\n');
								serverSentence = "String de imahen enviado";
							} catch (Exception e) {

								e.printStackTrace();
							}

						} else if (clientSentence.equals("SALIR")) {
							serverSentence = "318 OK Adi�s.";

							// AdminWindow.usuarioDesconectado(nombreUsuario);
							socketTemp.CerrarSocket();
							MapClientesConectados.remove(nombreUsuario);
							escuchando = false;

						}

						socketTemp.Escribir(serverSentence + "CLRF" + '\n'); // ENVIAR
																				// AL
																				// CLIENTE
																				// RESPUESTA
																				// ESTADO
																				// 2
					} catch (Exception e1) {

						e1.printStackTrace();
					}

					break;
				}
				case 3: {

					try {
						if (clientSentence.equals("GET_LOC")) {
							if (listaSensores.get(1).getEstado() == "OFF") {

								System.out
										.println("GPS off conectando con servidor");
								serverSentence = this.localizarCellId(CellID,
										nombreUsuario, claveUsuario);
							}
						}
						socketTemp.Escribir(serverSentence + "CLRF" + '\n'); // ENVIAR
																				// AL
																				// CLIENTE
																				// RESPUESTA
																				// ESTADO
																				// 3
					} catch (Exception e1) {

						e1.printStackTrace();
					}
					break;
				}
				}

			}

		} else {
			try {
				serverSentence = "ERROR MAXIMO NUMERO DE CLIENTES ALCANZADO";
				socketTemp.Escribir(serverSentence + '\n');
				socket.CerrarSocket();
			} catch (IOException e) {

				e.printStackTrace();
			}
		}

	}

	private String localizarCellId(int id) {
		// TODO Auto-generated method stub
		return null;
	}

	private String enviarImagen() throws Exception {
		 File file = new File("indice.jpg");
		 
		FileInputStream imageInFile = new FileInputStream(file);
		byte imageData[] = new byte[(int) file.length()];
		imageInFile.read(imageData);

		// Converting Image byte array into Base64 String
		String imageDataString = encodeImage(imageData);

		String linea = new String(imageDataString);
		return linea;
	}

	/**
	 * Encodes the byte array into base64 string
	 * 
	 * @param imageByteArray
	 *            - byte array
	 * @return String a {@link java.lang.String}
	 */
	public static String encodeImage(byte[] imageByteArray) {
		return Base64.encodeBase64URLSafeString(imageByteArray);
	}

	
	public Sensor buscarSensor(int id) {
		Sensor s = null;
		for (int i = 0; i < listaSensores.size(); i++) {
			if (listaSensores.get(i).getID_Sensor() == id)
				s = listaSensores.get(i);
		}
		return s;

	}

	private String localizarCellId(String cellId, String MRCV, String CLAVE) {
		String sentence = new String();
		String mensajerecibido = new String();
		try {
			SocketManager sm = new SocketManager("127.0.0.1", 2000);

			sentence = "USER " + MRCV;
			sm.Escribir(sentence + '\n');

			mensajerecibido = sm.Leer();
			System.out.println("* Desde el servidor de Localizacion: "
					+ mensajerecibido);
			if (mensajerecibido.equals("OK BienvenidoonCLRF")) {

				sentence = "PASS " + CLAVE;
				sm.Escribir(sentence + '\n');

				mensajerecibido = sm.Leer();
				System.out.println("* Desde el servidor de Localiacon: "
						+ mensajerecibido);
				if (mensajerecibido.equals("312 OK Bienvenido al sistemaCLRF")) {
					sentence = "GETCOOR " + cellId;
					sm.Escribir(sentence + '\n');

					mensajerecibido = sm.Leer();

				}
			}

			System.out.println("Fin ");
			sm.CerrarSocket();

		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println(mensajerecibido);
		mensajerecibido = mensajerecibido.substring(6);
		return mensajerecibido;
	}
}
